package com.niubilities.app.hosts_switcher.startup;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.Properties;

import org.apache.commons.exec.CommandLine;
import org.apache.commons.exec.DefaultExecutor;
import org.apache.commons.exec.ExecuteException;
import org.apache.commons.exec.ExecuteWatchdog;

import com.niubilities.app.hosts_switcher.utils.ClientUtils;

public class HostSwitcher {

	/**
	 * 	java.runtime.name  :  Java(TM) SE Runtime Environment
		awt.useSystemAAFontSettings  :  gasp
		sun.boot.library.path  :  /usr/local/lib/jvm/jdk1.8.0_101/jre/lib/amd64
		java.vm.version  :  25.101-b13
		java.vm.vendor  :  Oracle Corporation
		java.vendor.url  :  http://java.oracle.com/
		path.separator  :  :
		java.vm.name  :  Java HotSpot(TM) 64-Bit Server VM
		file.encoding.pkg  :  sun.io
		user.country  :  CN
		sun.java.launcher  :  SUN_STANDARD
		sun.os.patch.level  :  unknown
		java.vm.specification.name  :  Java Virtual Machine Specification
		user.dir  :  /home/chow/develop/eclipse_workspace/hosts_switcher
		java.runtime.version  :  1.8.0_101-b13
		java.awt.graphicsenv  :  sun.awt.X11GraphicsEnvironment
		java.endorsed.dirs  :  /usr/local/lib/jvm/jdk1.8.0_101/jre/lib/endorsed
		os.arch  :  amd64
		java.io.tmpdir  :  /tmp
		line.separator  :  
		
		java.vm.specification.vendor  :  Oracle Corporation
		os.name  :  Linux
		sun.jnu.encoding  :  UTF-8
		java.library.path  :  /usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib
		java.specification.name  :  Java Platform API Specification
		java.class.version  :  52.0
		sun.management.compiler  :  HotSpot 64-Bit Tiered Compilers
		os.version  :  4.4.0-2-deepin-amd64
		user.home  :  /home/chow
		user.timezone  :  
		java.awt.printerjob  :  sun.print.PSPrinterJob
		file.encoding  :  UTF-8
		java.specification.version  :  1.8
		java.class.path  :  /home/chow/develop/eclipse_workspace/hosts_switcher/target/classes:/home/chow/.p2/pool/plugins/org.junit_4.12.0.v201504281640/junit.jar:/home/chow/.p2/pool/plugins/org.hamcrest.core_1.3.0.v201303031735.jar:/home/chow/develop/.m2/repository/org/apache/httpcomponents/httpclient/4.5.2/httpclient-4.5.2.jar:/home/chow/develop/.m2/repository/org/apache/httpcomponents/httpcore/4.4.4/httpcore-4.4.4.jar:/home/chow/develop/.m2/repository/commons-logging/commons-logging/1.2/commons-logging-1.2.jar:/home/chow/develop/.m2/repository/commons-codec/commons-codec/1.9/commons-codec-1.9.jar
		user.name  :  chow
		java.vm.specification.version  :  1.8
		sun.java.command  :  HostSwitcher
		java.home  :  /usr/local/lib/jvm/jdk1.8.0_101/jre
		sun.arch.data.model  :  64
		user.language  :  zh
		java.specification.vendor  :  Oracle Corporation
		awt.toolkit  :  sun.awt.X11.XToolkit
		java.vm.info  :  mixed mode
		java.version  :  1.8.0_101
		java.ext.dirs  :  /usr/local/lib/jvm/jdk1.8.0_101/jre/lib/ext:/usr/java/packages/lib/ext
		sun.boot.class.path  :  /usr/local/lib/jvm/jdk1.8.0_101/jre/lib/resources.jar:/usr/local/lib/jvm/jdk1.8.0_101/jre/lib/rt.jar:/usr/local/lib/jvm/jdk1.8.0_101/jre/lib/sunrsasign.jar:/usr/local/lib/jvm/jdk1.8.0_101/jre/lib/jsse.jar:/usr/local/lib/jvm/jdk1.8.0_101/jre/lib/jce.jar:/usr/local/lib/jvm/jdk1.8.0_101/jre/lib/charsets.jar:/usr/local/lib/jvm/jdk1.8.0_101/jre/lib/jfr.jar:/usr/local/lib/jvm/jdk1.8.0_101/jre/classes
		java.vendor  :  Oracle Corporation
		file.separator  :  /
		java.vendor.url.bug  :  http://bugreport.sun.com/bugreport/
		sun.io.unicode.encoding  :  UnicodeLittle
		sun.cpu.endian  :  little
		sun.desktop  :  gnome
		sun.cpu.isalist  :  
	 * @param args
	 */
	private static final String OS_NAME = "os.name";
	private static final String LINUX = "Linux";
	private static final String WINDOWS = "Windows";
	
	private static final String HOSTS_FILENAME = "hosts";
	private static final String HOSTS_BACKUP_FILENAME = "hosts.back";
	
	private static final String LINUX_HOST_PATH = "/etc/";
	private static final String WINDOWS_HOST_PATH = "c://windows/System32/drivers/etc/";
	
	private static final String LINUX_FLUSH_DNS = "systemctl restart NetworkManager";
	private static final String WINDWOS_FLUSH_DNS = "ipconfig /flushdns";
	
	private String currentOS = null;
	
	/**
	 * 
	 * @param method
	 * @param url
	 * @param map
	 * @return
	 */
	private String getHostsContent(String method, String url, Map<String,String> map) {
		String result = null;
		ClientUtils cu = new ClientUtils();
		try {
			result = cu.get(url, map);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return result;
	}
	
	private String checkOS() {
		String result = null;
		String osName = System.getProperty(OS_NAME);
		if (osName != null && !osName.isEmpty()) {
			result = osName.contains(LINUX) ? LINUX : WINDOWS;
		}
		return result;
	}
	/**
	 * Please check the content before invoke this method.
	 * @param content
	 * @return
	 */
	private boolean switchHosts(String content) {
		if(content == null || content.isEmpty()) 
			return false;
		boolean result = false;
		File hostFile = null;
		String filePath = "";
		String osName = getCurrentOS();
		
		if(osName != null && !osName.isEmpty()) {
			
			if(osName.contains(LINUX)) {
				filePath = LINUX_HOST_PATH;
			} else {
				//The os is Windows
				filePath = WINDOWS_HOST_PATH;
			}
			
			if(!filePath.isEmpty()) {
				hostFile = new File(filePath + HOSTS_FILENAME);	
			}
			
			if (hostFile != null) {
				File backHosts = new File(filePath + HOSTS_BACKUP_FILENAME);
				if(!backHosts.exists()) {
					if(hostFile.exists())
						hostFile.renameTo(backHosts);
				}
			
				FileOutputStream fos = null;
				try {
					fos = new FileOutputStream(hostFile);
					fos.write(content.getBytes());
					fos.flush();
					result = true;
				} catch (IOException e) {
					e.printStackTrace();
				} finally {
					try {
						if(fos != null)
							fos.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}
		}
		return result;
	}
	
	private boolean flushDNS() {
		boolean result = false;
		String osName = getCurrentOS();
		String cmdLineStr = null;
		final int SUCCESS_FLAG = 0;
		if(osName != null && !osName.isEmpty()) {
			cmdLineStr = osName.contains(LINUX) ? LINUX_FLUSH_DNS : WINDWOS_FLUSH_DNS;
			System.out.println("Current OS is " + osName + ", flush cmd is " + cmdLineStr);
			CommandLine cmdLine = CommandLine.parse(cmdLineStr);
			DefaultExecutor executor = new DefaultExecutor();
			executor.setExitValue(SUCCESS_FLAG);
			ExecuteWatchdog watchdog = new ExecuteWatchdog(60000);
			executor.setWatchdog(watchdog);
			try {
				int exitValue = executor.execute(cmdLine);
				if(exitValue == SUCCESS_FLAG) {
					result = true;
				}
			} catch (ExecuteException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return result;
	}
	public static void main(String[] args) {
		Properties p = new Properties();
		InputStream is = null;
		try {
		    is = HostSwitcher.class.getClassLoader().getResourceAsStream("config.properties");
		    if(is == null){
		        System.out.println("Please create a file named \"config.properties\" at this directory with \"url = 'the url have the hosts'\"");
		        return ;
		    }
			p.load(is);
			String url = p.getProperty("url");
			if(url != null && !url.isEmpty()) {
				HostSwitcher hs = new HostSwitcher();
				String content = hs.getHostsContent(null, url, null);
				if(!hs.switchHosts(content)) {
					System.out.println("Change the hosts failed!!!");
				}
				
				else {
					System.out.println("Change the hosts SUCCESSFULLY!!!");
					if(!hs.flushDNS()) {
						System.out.println("Flush DNS failed! Please flush by yourself to make the hosts work!");
					} else {
						System.out.println("Flush DNS SUCCESSFULLY!!! Go to the google to check the hosts works or not!");
					}
				}
			}
			else {
				System.out.println("Change the hosts failed!!!");
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		
//		Properties p = System.getProperties();
//		Set<Object> set = p.keySet();
//		Iterator<Object> i = set.iterator();
//		while (i.hasNext()) {
//			String s = i.next().toString();
//			String pro = p.getProperty(s);
//			System.out.println(s + "  :  " + pro);
//		}
		// File f = new File("/etc/")
	}

	public  String getCurrentOS() {
		if(currentOS == null) {
			currentOS = checkOS();
		}
		return currentOS;
	}

}
